package com.ktwlsoft.fundmanage.domain.business;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.ktwlsoft.fundmanage.domain.entity.*;
import com.ktwlsoft.fundmanage.domain.entity.BaseFundRecord.State;
import com.ktwlsoft.fundmanage.domain.entity.FundSuperviseAccept.ContractApproval;
import com.ktwlsoft.fundmanage.domain.entity.pictureconfig.SignCredential;
import com.ktwlsoft.fundmanage.domain.entity.pictureconfig.SignCredentialInfo;
import com.ktwlsoft.fundmanage.domain.repository.*;
import com.ktwlsoft.fundmanage.mapper.CurrencyMapper;
import com.ktwlsoft.fundmanage.mapper.IFundRecordMapper;
import com.ktwlsoft.fundmanage.mapper.IFundSuperviseAcceptMapper;
import com.ktwlsoft.fundmanage.payload.IAccountUser;
import com.ktwlsoft.fundmanage.payload.exceptions.BusinessError;
import com.ktwlsoft.fundmanage.payload.fundIn.*;
import com.ktwlsoft.fundmanage.service.pictureconfig.SignCredentialInfoService;
import com.ktwlsoft.fundmanage.service.pictureconfig.SignCredentialService;
import com.ktwlsoft.fundmanage.utils.DateUtils;
import com.ktwlsoft.fundmanage.utils.KeyWorkerUtil;
import com.ktwlsoft.fundmanage.utils.UserUtils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.ktwlsoft.fundmanage.payload.BaseResult;
import com.ktwlsoft.fundmanage.payload.ResultType;
import com.ktwlsoft.fundmanage.payload.Contract.EditContractRequest;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;

import static com.ktwlsoft.fundmanage.payload.BaseResult.body;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Fund record in service.
 *
 * @author LanJian
 */
@Service
public class FundInService extends BaseBusiness {

    /**
     * fund in repositpory
     */
    private final FundSuperviseAcceptRepository fundSuperviseAcceptRepository;

    private final ActionLogRepository actionLogRepository;

    private final FundInRecordRepository fundInRecordRepository;

    @Autowired
    private FundOutRecordRepository fundOutRecordReporitory;

    private final IFundRecordMapper fundRecordMapper;

    private final HouseRelatedPersonRepository houseRelatedPersonRepository;

    private final RelationalPersonBankRepository relationalPersonBankRepository;

    private final IFundSuperviseAcceptMapper fundSuperviseAcceptMapper;

    private final BusinessProtocolRepository businessProtocolRepository;

    private final TransferApplyRepository transferApplyRepository;

    private final CurrencyMapper currencyMapper;

    private final SignCredentialService signCredentialService;

    private final SignCredentialInfoService signCredentialInfoService;

    public FundInService(FundSuperviseAcceptRepository fundSuperviseAcceptRepository,
                         ActionLogRepository actionLogRepository, FundInRecordRepository fundInRecordRepository,
                         IFundRecordMapper fundRecordMapper, HouseRelatedPersonRepository houseRelatedPersonRepository,
                         RelationalPersonBankRepository relationalPersonBankRepository,
                         IFundSuperviseAcceptMapper fundSuperviseAcceptMapper, BusinessProtocolRepository businessProtocolRepository,
                         TransferApplyRepository transferApplyRepository, CurrencyMapper currencyMapper,
                         SignCredentialService signCredentialService, SignCredentialInfoService signCredentialInfoService) {
        this.fundSuperviseAcceptRepository = fundSuperviseAcceptRepository;
        this.actionLogRepository = actionLogRepository;
        this.fundInRecordRepository = fundInRecordRepository;
        this.fundRecordMapper = fundRecordMapper;
        this.houseRelatedPersonRepository = houseRelatedPersonRepository;
        this.relationalPersonBankRepository = relationalPersonBankRepository;
        this.fundSuperviseAcceptMapper = fundSuperviseAcceptMapper;
        this.businessProtocolRepository = businessProtocolRepository;
        this.transferApplyRepository = transferApplyRepository;
        this.currencyMapper = currencyMapper;
        this.signCredentialService = signCredentialService;
        this.signCredentialInfoService = signCredentialInfoService;
    }

    /**
     * Save the fund
     *
     * @param fundSuperviseAccept entity to persist into database.
     * @return if success, return the saved fund info, or error messages.
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> save(FundSuperviseAccept fundSuperviseAccept) {
        try {
            List<SignCredential> signCredentials = fundSuperviseAccept.getSignCredentials();
            IAccountUser user = UserUtils.getUser();
            fundSuperviseAccept.init();
            fundSuperviseAccept.setUserName(user.getName());
            fundSuperviseAccept.setUserId(user.getUserId());
            fundSuperviseAccept.setTsCode(KeyWorkerUtil.nextId());
            fundSuperviseAccept.setAmountLeft(BigDecimal.ZERO);
            fundSuperviseAccept.setContractApproval(null);
            fundSuperviseAccept.setContractApproval(FundSuperviseAccept.ContractApproval.START);
            fundSuperviseAccept.setAcceptState(FundSuperviseAccept.AcceptState.HANDING);
            if (fundSuperviseAccept.isLoanExist()) {
                if (fundSuperviseAccept.getDownAmount().compareTo(BigDecimal.ZERO) > 0) {
                    fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DOWN_NOT_PAID);
                } else {
                    fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.LOAN_NOT_PAID);
                }
            } else {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.UNPAID);
            }
            for (HouseRelatedPerson person : fundSuperviseAccept.getHouseRelatedPersonList()) {
                person.setId(KeyWorkerUtil.nextId());
                person.setTsCode(fundSuperviseAccept.getTsCode());
                houseRelatedPersonRepository.save(person);
            }
            fundSuperviseAccept = fundSuperviseAcceptRepository.save(fundSuperviseAccept);
            this.updateFiles(String.valueOf(fundSuperviseAccept.getTsCode()), signCredentials);
            return BaseResult.ok(fundSuperviseAccept);
        } catch (Exception e) {
            return BaseResult.body(fundSuperviseAccept, ResultType.SAVING_ERROR).withMessage(e.getMessage());
        }
    }

    /**
     * update business
     *
     * @param fundSuperviseAccept entity to persist into database.
     * @return if success, return the saved fund info, or error messages.
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> updateBusiness(FundSuperviseAccept fundSuperviseAccept) {
        JSONObject object = conditionInspect(fundSuperviseAccept);
        if (object.getBoolean("state")) {
            return BaseResult.body(fundSuperviseAccept, ResultType.BUSINESS_ERROR)
                    .withMessage(object.getString("message"));
        }
        try {
            // houseRelatedPersonRepository.deleteByTsCode(fundSuperviseAccept.getTsCode());
            List<HouseRelatedPerson> existPersons = houseRelatedPersonRepository
                    .findByTsCode(fundSuperviseAccept.getTsCode());
            List<HouseRelatedPerson> newPersons = fundSuperviseAccept.getHouseRelatedPersonList();
            this.updateFiles(String.valueOf(fundSuperviseAccept.getTsCode()), fundSuperviseAccept.getSignCredentials());
            for (HouseRelatedPerson person : newPersons) {
                if (person.getId() == null) {
                    person.setId(KeyWorkerUtil.nextId());
                } else {
                    for (int i = 0; i < existPersons.size(); i++) {
                        if (existPersons.get(i).getId().equals(person.getId())) {
                            existPersons.remove(i);
                        }
                    }
                }
                person.setTsCode(fundSuperviseAccept.getTsCode());
                houseRelatedPersonRepository.save(person);
            }
            for (HouseRelatedPerson person : existPersons) {
                houseRelatedPersonRepository.deleteById(person.getId());
            }
            fundSuperviseAccept = fundSuperviseAcceptRepository.save(fundSuperviseAccept);
            return BaseResult.ok(fundSuperviseAccept);
        } catch (Exception e) {
            return BaseResult.body(fundSuperviseAccept, ResultType.SAVING_ERROR).withMessage(e.getMessage());
        }
    }

    public void updateFiles(String busi, List<SignCredential> signCredentials) {
        signCredentialService.deleteByBusiId(busi);
        signCredentialInfoService.deleteByBusiId(busi);
        signCredentialInfoService.save(signCredentials, busi);
    }

    /**
     * Check whether the TsCode relational record existed.
     *
     * @param tsCode trade code.
     * @return if existed, return true or false if not existed
     */
    public boolean businessExist(long tsCode) {
        try {
            return fundSuperviseAcceptRepository.existsByTsCode(tsCode);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 保存协议
     *
     * @param businessProtocol 协议实体
     * @return 协议
     */
    @Transactional(rollbackFor = Exception.class)
    public BusinessProtocol saveProtocol(EditContractRequest protocalRequest) {
        BusinessProtocol businessProtocol = businessProtocolRepository.findByTsCode(protocalRequest.getTsCode());
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository
                .findByTsCode(protocalRequest.getTsCode());
        if (businessProtocol == null) {
            // 协议不存在, 新增协议，默认为审核通过。
            businessProtocol = new BusinessProtocol();
            businessProtocol.setId(KeyWorkerUtil.nextId());
            businessProtocol.setContent(protocalRequest.getContent());
            businessProtocol.setTsCode(protocalRequest.getTsCode());
            businessProtocol.setPrinted(false);
            fundSuperviseAccept.setContractApproval(ContractApproval.PASS);
        } else {
            if (businessProtocol.getContent() != null) {
                businessProtocol.setContent(new String());
            }
            // 比较协议
            if (businessProtocol.getContent().equals(protocalRequest.getContent())) {
                // 相同，无变化
                fundSuperviseAccept.setContractApproval(ContractApproval.PASS);
            } else {
                // 不同，有变化
                businessProtocol.setNewContent(protocalRequest.getContent());
                businessProtocol.setPrinted(false);
                fundSuperviseAccept.setContractApproval(ContractApproval.WAITING);
            }
            fundSuperviseAcceptRepository.save(fundSuperviseAccept);

        }
        return businessProtocolRepository.save(businessProtocol);
    }

    /**
     * 返回协议内容
     *
     * @param tsCode 案件编号
     * @return 案件协议内容
     */
    public BaseResult findBusinessProtocal(long tsCode) {
        BusinessProtocol protocal = businessProtocolRepository.findByTsCode(tsCode);
        return BaseResult.ok(protocal);
    }

    /**
     * 取消对账
     *
     * @param fundInId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> cancelFundInCheck(long fundInId, String processInstanceId, String cancelReson) {
        FundInRecord fundInRecord = fundInRecordRepository.findByFCode(fundInId).get(0);
        if (fundInRecord == null) {
            return BaseResult.body("", ResultType.BUSINESS_ERROR).withMessage("交款信息不存在");
        }
        IAccountUser user = UserUtils.getUser();
        if (user == null) {
            return BaseResult.body("基础平台未能正确获取到用户信息", ResultType.BUSINESS_ERROR);
        }
        fundInRecord.setCancelName(user.getName());
        fundInRecord.setCancelId(user.getUserId());
        fundInRecord.setCancelReson(cancelReson);
        fundInRecord.setCancelDate(new Date());
        if (fundInRecord.isPayCheck()) {
            if (fundInRecord.getDnCode() != null && transferApplyRepository.existsById(fundInRecord.getDnCode())) {
                return BaseResult.body("", ResultType.BUSINESS_ERROR).withMessage("存在划款单");
            }
            fundSuperviseAcceptRepository.subAmouteLeft(fundInRecord.getAmount(), fundInRecord.getTsCode());
        }
        fundInRecord.setPayCheck(false);
        // fundInRecord.setReturn(true);
        // fundInRecord.setState(BaseFundRecord.State.CANCEL);
        // fundInRecord.setFlowInstanceId(processInstanceId);
        fundInRecordRepository.save(fundInRecord);
        return BaseResult.ok("OK");
    }

    @Transactional(rollbackFor = Exception.class)
    public void setContractApprovel(ContractApprovalRequest request, String auditor, String auditorId)
            throws Exception {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(request.getTsCode());
        BusinessProtocol businessProtocol = businessProtocolRepository.findByTsCode(request.getTsCode());
        if (fundSuperviseAccept == null) {
            throw new Exception("案件未找到, 交易编号：" + request.getTsCode());
        }
        if (request.getApproval()) {
            // 审核通过
            fundSuperviseAccept.setContractApproval(ContractApproval.PASS);
            businessProtocol.setContent(businessProtocol.getNewContent());
        } else {
            // 审核不通过
            fundSuperviseAccept.setContractApproval(ContractApproval.UNPASS);
        }
        fundSuperviseAcceptRepository.save(fundSuperviseAccept);
        businessProtocolRepository.save(businessProtocol);
    }

    /**
     * 业务受理分页列表
     *
     * @param pageable 分页参数
     * @return 分页列表
     */
    public BaseResult<?> businessFindAll(Long tsCode, String districtCode, Date from, Date to,
                                         FundSuperviseAccept.AcceptState acceptState, Pageable pageable) {
        try {
            return BaseResult.ok(fundSuperviseAcceptRepository
                    .findByTsCodeAndDistrictCodeAndCreatedAtGreaterThanAndCreatedAtLessThanAndAcceptState(tsCode,
                            districtCode, from, to, acceptState, pageable));
        } catch (Exception e) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage(e.getMessage());
        }
    }

    /**
     * Save action exceptions
     *
     * @param actionLog action entity
     */
    public void saveLog(ActionLog actionLog) {
        actionLogRepository.save(actionLog);
    }

    /**
     * Check if the business contract has been printed more than [times]
     *
     * @param tsCode business code
     * @param times  printed times
     * @return
     */
    public boolean contractPrintedMoreThan(Long tsCode, int times) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        return fundSuperviseAccept.getPrintTimes() >= times;
    }

    public FundInRecord findFundInResult(Long fCode) {
        List<FundInRecord> fundInRecords = fundInRecordRepository.findByFCode(fCode);
        if (fundInRecords.size() == 1) {
            return fundInRecords.get(0);
        } else {
            return null;
        }
    }

    /**
     * 资金录入恢复已划款金额！
     *
     * @param fCode
     * @param amount
     * @return
     */
    public int fundInRestore(long fCode, BigDecimal amount) {
        return fundInRecordRepository.restoreTransferedAmount(amount, fCode);
    }

    /**
     * 保存资金录入记录
     *
     * @param fundInRecord 资金实体
     * @return 已录入资金实体
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> saveFund(FundInRecord fundInRecord) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(fundInRecord.getTsCode());
        BusinessProtocol businessProtocol = businessProtocolRepository.findByTsCode(fundInRecord.getTsCode());
        // 判断案件的合同是否审核通过
        if (fundSuperviseAccept.getContractApproval() == FundSuperviseAccept.ContractApproval.PASS) {
            if (!businessProtocol.isPrinted()) {
                return BaseResult.body("合同未打印", ResultType.BUSINESS_ERROR).withMessage("合同未打印");
            }
        } else {
            return BaseResult.body("合同未审核通过", ResultType.BUSINESS_ERROR).withMessage("合同未审核通过");
        }

        if (fundInRecord.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return BaseResult.body("交款金额不能小于等于0", ResultType.BUSINESS_ERROR).withMessage("交款金额不能小于等于0");
        }
        if (fundInRecord.getFCode() == null) {
            fundInRecord.setFCode(KeyWorkerUtil.nextId());
        }
        fundInRecord.setFlowCode(KeyWorkerUtil.nextId());
        fundInRecord.setState(BaseFundRecord.State.NORMAL);
        fundInRecordRepository.save(fundInRecord);
        return BaseResult.ok(fundInRecord);
    }

    public BaseResult<?> saveFundDirec(FundInRecord fundInRecord) {
        if (fundInRecord.getFCode() == null || fundInRecord.getFCode() == 0L) {
            throw new BusinessError("资金回退修改：资金没有主键！");
        }
        fundInRecordRepository.save(fundInRecord);
        return BaseResult.ok(fundInRecord);
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> fundInAccountCheck(boolean approval, long fCode, String auditor, String auditorId, Long tsCode,
                                            BaseFundRecord.State state, Date checkTime) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        FundInRecord fundInRecord = fundInRecordRepository.findById(fCode).orElse(null);
        fundInRecord.setPayCheck(approval);
        fundInRecord.setPayCheckTime(checkTime);
        fundInRecord.setPayChecker(auditor);
        fundInRecord.setPayCheckerId(auditorId);
        fundInRecord.setState(state);
        if (!approval) {
            return BaseResult.ok("对账结束, 对账不通过！");
        }
        updateState(tsCode, fundSuperviseAccept, fundInRecord);
        return BaseResult.ok("对账成功");
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    private void updateState(Long tsCode, FundSuperviseAccept fundSuperviseAccept, FundInRecord fundInRecord) {
        // 初始化首付金额，临时数据
        fundSuperviseAccept.init();
        // 贷款情况
        if (fundSuperviseAccept.isLoanExist()) {

            // 贷款是否结束
            boolean isLoanOver = false;
            // 首付是否结束
            boolean isDownOver = false;

            // 当前所有首付金额（包括所有对账和未对账的）
            BigDecimal downPayAmount = fundInRecordRepository.queryDownPay(fundInRecord.getTsCode());
            if (downPayAmount == null) {
                downPayAmount = BigDecimal.ZERO;
            }
            // 当前所有贷款金额（包括所有对账和未对账的），如果付过，那么应该和案件的额定贷款金额一致，如果没付过，那么应该为0
            BigDecimal loanPayAmount = fundInRecordRepository.queryLoan(fundInRecord.getTsCode());
            if (loanPayAmount == null) {
                loanPayAmount = BigDecimal.ZERO;
            }

            // 对比当前已付所有首付金额和案件额定首付金额
            int downResult = downPayAmount.compareTo(fundSuperviseAccept.getDownAmount());
            if (downResult > 0) {
                throw new BusinessError("首付过多！");
            } else if (downResult == 0) {
                isDownOver = true;
            } else {
                isDownOver = false;
            }
            // 当前贷款金额是否付过？
            if (loanPayAmount.compareTo(BigDecimal.ZERO) > 0) {
                // 对比当前已付贷款金额和案件额定贷款金额
                int loanResult = loanPayAmount.compareTo(fundSuperviseAccept.getLoanAmount());
                if (loanResult > 0) {
                    throw new BusinessError("贷款过多");
                } else if (loanResult < 0) {
                    throw new BusinessError("贷款未一次性缴清");
                } else {
                    isLoanOver = true;
                }
            }
            if (!isDownOver && !isLoanOver) {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DOWN_NOT_PAID_ALL);
            } else if (isDownOver && !isLoanOver) {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.LOAN_NOT_PAID);
            } else if (!isDownOver && isLoanOver) {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DOWN_NOT_PAID_ALL);
            } else {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DONE);
            }
        } else {
            // 全款付情况
            BigDecimal payedAll = fundInRecordRepository.getPayAll(fundSuperviseAccept.getTsCode());
            if (payedAll == null) {
                payedAll = BigDecimal.ZERO;
            }
            // payedAll = payedAll.add(fundInRecord.getAmount());
            int fullResult = payedAll.compareTo(fundSuperviseAccept.getSuperviseAmount());
            if (fullResult == 0) {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DONE);
            } else if (fullResult > 0) {
                throw new BusinessError("全款交多了！");
            } else {
                fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.NOT_PAID_ALL);
            }
        }
        if (!fundSuperviseAccept.restore(fundInRecord.getAmount())) {
            throw new BusinessError("对账失败, 入账过多");
        }
        if (fundSuperviseAcceptRepository.addAmouteLeft(fundInRecord.getAmount(), tsCode) == 0) {
            throw new BusinessError("此条数据未能成功对账，因为有其他访问，请再试一次");
        }
    }

    /**
     * 获取业务详情
     *
     * @param tsCode
     * @return
     */
    public BaseResult<?> findBusiness(long tsCode) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        fundSuperviseAccept
                .setHouseRelatedPersonList(houseRelatedPersonRepository.findByTsCode(fundSuperviseAccept.getTsCode()));
        JSONObject object1 = new JSONObject();
        object1.put("tsCode", fundSuperviseAccept.getTsCode());
        fundSuperviseAccept.setFundInRecords(fundRecordMapper.findFundInRecord(object1));
        return BaseResult.ok(fundSuperviseAccept);
    }

    /**
     * @param tsCode
     * @return
     */
    public FundSuperviseAccept findBusinessByTsCode(long tsCode) {
        return fundSuperviseAcceptRepository.findByTsCode(tsCode);
    }

    /**
     * 案件划走划款金额
     *
     * @param amount
     * @param tsCode
     * @return
     */
    public int businessSubTransfer(BigDecimal amount, Long tsCode) {
        return fundSuperviseAcceptRepository.subAmouteLeft(amount, tsCode);
    }

    /**
     * 案件撤回划款金额
     *
     * @param amount
     * @param tsCode
     * @return
     */
    public int businessAddTransfer(BigDecimal amount, Long tsCode) {
        return fundSuperviseAcceptRepository.addAmouteLeft(amount, tsCode);
    }

    /**
     * 业务列表
     *
     * @param tsCode          交易编号
     * @param from            时间起
     * @param to              时间止
     * @param districtCode    区域编码
     * @param contractArroval 协议是否通过
     * @param pageable        分页信息
     * @return
     */
    public BaseResult<?> findPageByContract(long tsCode, Date from, Date to, String districtCode,
                                            FundSuperviseAccept.ContractApproval contractArroval, FundSuperviseAccept.AcceptState acceptState,
                                            Pageable pageable) {
        return BaseResult.ok(fundSuperviseAcceptRepository
                .findByTsCodeAndDistrictCodeAndContractApprovalAndCreatedAtGreaterThanAndCreatedAtLessThanAndAcceptState(
                        tsCode, districtCode, contractArroval, acceptState, from, to, pageable));
    }

    /**
     * 使用Example来进行业务查询
     *
     * @param businessRequest 业务请求参数
     * @param pageable        分页信息
     * @return 分页列表
     */
    public BaseResult<?> findBusinessPage(BusinessRequest businessRequest, Pageable pageable) {
        FundSuperviseAccept fundSuperviseAccept = new FundSuperviseAccept(businessRequest.getTsCode(),
                businessRequest.getContractApproval(), businessRequest.getAcceptState(), businessRequest.getDistrict());
        ExampleMatcher exampleMatcher = ExampleMatcher.matching().withIgnorePaths("loanExist", "guarantyExist",
                "loanAmount", "superviseAmount", "contractAmount", "loanPeriod", "constructionArea", "comprisingArea",
                "commonArea", "printTimes", "transferState", "recordState");
        Example<FundSuperviseAccept> example = Example.of(fundSuperviseAccept, exampleMatcher);
        return BaseResult.ok(fundSuperviseAcceptRepository.findAll(example, pageable));
    }

    public BaseResult<?> findFundSuperviseAcceptByExample(Example<FundSuperviseAccept> example, Pageable pageable) {
        return BaseResult.ok(fundSuperviseAcceptRepository.findAll(example, pageable));
    }

    /**
     * 查看资金流水 on 2019/9/4 14:25
     *
     * @param tsCode tsCode
     * @return BaseResult<?>
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> queryCapitalFlow(Long tsCode, String state) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        if (fundSuperviseAccept == null) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("资金受理业务不存在");
        }
        QueryCapitalFlowRequest queryCapitalFlowRequest = new QueryCapitalFlowRequest();
        BeanUtils.copyProperties(fundSuperviseAccept, queryCapitalFlowRequest);
        queryCapitalFlowRequest.setFundInRecords(fundInRecordRepository.findByTsCode(tsCode));
        if (queryCapitalFlowRequest.getFundInRecords() != null
                && queryCapitalFlowRequest.getFundInRecords().size() > 0) {
            List<Long> longs = Lists.newArrayList();
            for (FundInRecord fundInRecord : queryCapitalFlowRequest.getFundInRecords()) {
                longs.add(fundInRecord.getFCode());
            }
            List<FundOutRecord> outRecords = Lists.newArrayList();
            List<FundOutRecord> fundOutRecords = fundRecordMapper.findByIds(longs);
            outRecords.addAll(fundOutRecords);
            if (fundOutRecords.size() > 0) {
                for (FundOutRecord fundOutRecord : fundOutRecords) {
                    if (fundOutRecord.getState().toString().equals(state)) {
                        outRecords.remove(fundOutRecord);
                    }
                }
            }
            queryCapitalFlowRequest.setFundOutRecords(outRecords);

        }
        queryCapitalFlowRequest.setHouseRelatedPersonList(houseRelatedPersonRepository.findByTsCode(tsCode));
        return BaseResult.body(queryCapitalFlowRequest, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 获取买卖双方 on 2019/9/5 10:03
     *
     * @param tsCode tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> getRelationalPersonBank(Long tsCode) {
        return BaseResult.body(houseRelatedPersonRepository.findByTsCode(tsCode), ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 获取房屋关系人银行 on 2019/9/5 10:19
     *
     * @param relatedPersonId relatedPersonId @return BaseResult<?> @throws
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> getRelationalBank(Long relatedPersonId, String operationType) {
        JSONObject object = new JSONObject();
        if (relatedPersonId != null && relatedPersonId > 0) {
            object.put("relatedPersonId", relatedPersonId);
        }
        if (operationType != null && !"".equals(operationType.trim())) {
            object.put("operationType", operationType);
        }
        List<RelationalPersonBank> list = currencyMapper.findByRelatedPersonId(object);
        if (list != null && list.size() > 0) {
            List<HouseRelatedPerson> personList = houseRelatedPersonRepository.findAll();
            if (personList.size() > 0) {
                list.forEach(rp -> {
                    personList.forEach(hp -> {
                        if (hp.getId().equals(rp.getRelatedPersonId())) {
                            rp.setHouseRelatedPerson(hp);
                        }
                    });
                });
            }
        }
        return BaseResult.body(list, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 关系人银行新增或修改 on 2019/9/5 10:18
     *
     * @param personBank personBank
     * @return BaseResult<?>
     */
    public BaseResult<?> relationalPersonBankSave(RelationalPersonBank personBank) {
        if (personBank.getRelatedPersonId() == null || personBank.getRelatedPersonId() == 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("房屋关系人不能为空");
        }
        if (personBank.getPersonnelType() == null || "".equals(personBank.getPersonnelType().toString().trim())) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("关系类型为空");
        }
        if (personBank.getId() == null || personBank.getId() == 0) {
            personBank.setId(KeyWorkerUtil.nextId());
            personBank.setCreatedAt(new Date());
        }
        personBank.setUpdatedAt(new Date());
        try {
            relationalPersonBankRepository.save(personBank);
            HouseRelatedPerson houseRelatedPerson = houseRelatedPersonRepository
                    .findById(personBank.getRelatedPersonId()).orElse(null);
            if (houseRelatedPerson != null) {
                houseRelatedPerson.setIsConfigBank(true);
                houseRelatedPersonRepository.save(houseRelatedPerson);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BaseResult.body(personBank, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 关系人银行删除 on 2019/9/5 10:29
     *
     * @param personBank personBank
     * @return BaseResult<?>
     */
    public BaseResult<?> relationalPersonBankDelete(RelationalPersonBank personBank) {
        try {
            relationalPersonBankRepository.delete(personBank);
        } catch (Exception e) {
            e.printStackTrace();
            return BaseResult.body(null, ResultType.DELETE_ERROR);
        }
        return BaseResult.body(personBank, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 产权过户 on 2019/9/9 9:56
     *
     * @param tsCode          交易编号
     * @param ownershipNo     所有权证号
     * @param signCredentials 要件(图片)集合
     * @return BaseResult<?>
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> propertyRightTransfer(Long tsCode, String ownershipNo, List<SignCredential> signCredentials) {
        if (tsCode == null || tsCode <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("tsCode为空");
        }
        if (ownershipNo == null || "".equals(ownershipNo.trim())) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("所有权证号为空");
        }
        if (signCredentials == null || signCredentials.size() <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("买方不动产权图片为空");
        }
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        if (fundSuperviseAccept.getTsCode() <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("该数据不存在");
        }
        // 所有权证号
        fundSuperviseAccept.setOwnershipNo(ownershipNo);
        // 所有权证号-旧
        fundSuperviseAccept.setOldOwnershipNo(fundSuperviseAccept.getOwnershipNo());
        // 是否过户
        fundSuperviseAccept.setTransferState(true);
        try {
            fundSuperviseAcceptRepository.save(fundSuperviseAccept);
            for (SignCredential credential : signCredentials) {
                credential.setBusiId(String.valueOf(tsCode));
                signCredentialService.signCredentialUpdate(credential);
                if (credential.getInfoList() != null && credential.getInfoList().size() > 0) {
                    for (SignCredentialInfo info : credential.getInfoList()) {
                        info.setBusiId(String.valueOf(tsCode));
                        info.setCredentialId(credential.getCredentialId());
                        signCredentialInfoService.signCredentialInfoUpdate(info);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return BaseResult.body(null, ResultType.BUSINESS_ERROR);
        }
        return BaseResult.body(fundSuperviseAccept, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 资金受理业务列表 on 2019/9/10 9:47
     *
     * @param findBusinessPageRequest findBusinessPageRequest
     * @return BaseResult<?>
     */
    public BaseResult<?> getBusinessPage(FindBusinessPageRequest findBusinessPageRequest) {
        JSONObject jsonObject = new JSONObject();
        IAccountUser user = UserUtils.getUser();
        if (findBusinessPageRequest.getRequestType() != null && findBusinessPageRequest.getRequestType() == 1) {
            if (user.getUserId() == null || "".equals(user.getUserId().trim())) {
                return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("获取不到当前用户");
            }
            jsonObject.put("userId", user.getUserId());
        }
        if (findBusinessPageRequest.getKeyWords() != null && !"".equals(findBusinessPageRequest.getKeyWords())) {
            jsonObject.put("keyWords", findBusinessPageRequest.getKeyWords());
        }
        if (findBusinessPageRequest.getDistrictCode() != null
                && !"".equals(findBusinessPageRequest.getDistrictCode().trim())) {
            jsonObject.put("districtCode", findBusinessPageRequest.getDistrictCode());
        }
        if (findBusinessPageRequest.getAcceptanceDataStart() != null
                && !"".equals(findBusinessPageRequest.getAcceptanceDataStart().trim())) {
            jsonObject.put("acceptanceDataStart",
                    DateUtils.dayMinTime(findBusinessPageRequest.getAcceptanceDataStart()));
        }
        if (findBusinessPageRequest.getAcceptanceDataEnd() != null
                && !"".equals(findBusinessPageRequest.getAcceptanceDataEnd().trim())) {
            jsonObject.put("acceptanceDataEnd", DateUtils.dayMaxTime(findBusinessPageRequest.getAcceptanceDataEnd()));
        }
        if (findBusinessPageRequest.getAcceptState() != null) {
            jsonObject.put("acceptState", findBusinessPageRequest.getAcceptState().toString());
        }
        if (findBusinessPageRequest.getContractApproval() != null) {
            jsonObject.put("contractApproval", findBusinessPageRequest.getContractApproval().toString());
        }
        if (findBusinessPageRequest.getTransferState() != null) {
            jsonObject.put("transferState", findBusinessPageRequest.getTransferState());
        }
        if (findBusinessPageRequest.getRecordState() != null) {
            jsonObject.put("recordState", findBusinessPageRequest.getRecordState());
        }
        if (findBusinessPageRequest.getFundState() != null) {
            jsonObject.put("fundState", findBusinessPageRequest.getFundState());
        }
        if (findBusinessPageRequest.getPn() <= 0) {
            findBusinessPageRequest.setPn(1);
        }
        if (findBusinessPageRequest.getPageSize() <= 0) {
            findBusinessPageRequest.setPageSize(30);
        }
        PageInfo<FundSuperviseAccept> pageInfo = findPage(findBusinessPageRequest.getPn(),
                findBusinessPageRequest.getPageSize(), jsonObject);
        if (pageInfo.getList() != null && pageInfo.getList().size() > 0) {
            List<HouseRelatedPerson> personList = houseRelatedPersonRepository.findAll();
            if (personList.size() > 0) {
                pageInfo.getList().forEach(value -> {
                    personList.forEach(value2 -> {
                        if (value2.getTsCode().equals(value.getTsCode())) {
                            if (value.getHouseRelatedPersonList() == null) {
                                value.setHouseRelatedPersonList(Lists.newArrayList());
                            }
                            value.getHouseRelatedPersonList().add(value2);
                        }
                    });
                    JSONObject object1 = new JSONObject();
                    object1.put("tsCode", value.getTsCode());
                    value.setFundInRecords(fundRecordMapper.findFundInRecord(object1));
                });
            }
        }
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 资金缴款-分页 on 2019/9/10 9:47
     *
     * @param findBusinessPageRequest findBusinessPageRequest
     * @return BaseResult<?>
     */
    public BaseResult<?> capitalPayment(FindBusinessPageRequest findBusinessPageRequest) {
        IAccountUser user = UserUtils.getUser();
        if (user.getUserId() == null || "".equals(user.getUserId().trim())) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("获取不到当前用户");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userId", user.getUserId());
        if (findBusinessPageRequest.getKeyWords() != null && !"".equals(findBusinessPageRequest.getKeyWords())) {
            jsonObject.put("keyWords", findBusinessPageRequest.getKeyWords());
        }
        if (findBusinessPageRequest.getDistrictCode() != null
                && !"".equals(findBusinessPageRequest.getDistrictCode().trim())) {
            jsonObject.put("districtCode", findBusinessPageRequest.getDistrictCode());
        }
        if (findBusinessPageRequest.getAcceptanceDataStart() != null
                && !"".equals(findBusinessPageRequest.getAcceptanceDataStart().trim())) {
            jsonObject.put("acceptanceDataStart",
                    DateUtils.dayMinTime(findBusinessPageRequest.getAcceptanceDataStart()));
        }
        if (findBusinessPageRequest.getAcceptanceDataEnd() != null
                && !"".equals(findBusinessPageRequest.getAcceptanceDataEnd().trim())) {
            jsonObject.put("acceptanceDataEnd", DateUtils.dayMaxTime(findBusinessPageRequest.getAcceptanceDataEnd()));
        }
        if (findBusinessPageRequest.getAcceptState() != null) {
            jsonObject.put("acceptState", findBusinessPageRequest.getAcceptState().toString());
        }
        if (findBusinessPageRequest.getContractApproval() != null) {
            jsonObject.put("contractApproval", findBusinessPageRequest.getContractApproval().toString());
        }
        if (findBusinessPageRequest.getTransferState() != null) {
            jsonObject.put("transferState", findBusinessPageRequest.getTransferState());
        }
        if (findBusinessPageRequest.getRecordState() != null) {
            jsonObject.put("recordState", findBusinessPageRequest.getRecordState());
        }
        if (findBusinessPageRequest.getFundState() != null && !"".equals(findBusinessPageRequest.getFundState())) {
            String s = "";
            boolean b = true;
            for (String s1 : findBusinessPageRequest.getFundState().split(",")) {
                if (b) {
                    s += "'" + s1 + "'";
                    b = false;
                } else {
                    s += ",'" + s1 + "'";
                }
            }
            jsonObject.put("fundState", s);
        }
        if (findBusinessPageRequest.getPn() <= 0) {
            findBusinessPageRequest.setPn(1);
        }
        if (findBusinessPageRequest.getPageSize() <= 0) {
            findBusinessPageRequest.setPageSize(30);
        }
        PageHelper.startPage(findBusinessPageRequest.getPn(), findBusinessPageRequest.getPageSize());
        PageInfo<FundSuperviseAccept> pageInfo = new PageInfo<>(fundSuperviseAcceptMapper.capitalPayment(jsonObject));
        if (pageInfo.getList() != null && pageInfo.getList().size() > 0) {
            List<HouseRelatedPerson> personList = houseRelatedPersonRepository.findAll();
            if (personList.size() > 0) {
                pageInfo.getList().forEach(value -> {
                    personList.forEach(value2 -> {
                        if (value2.getTsCode().equals(value.getTsCode())) {
                            if (value.getHouseRelatedPersonList() == null) {
                                value.setHouseRelatedPersonList(Lists.newArrayList());
                            }
                            value.getHouseRelatedPersonList().add(value2);
                        }
                    });
                    JSONObject object1 = new JSONObject();
                    object1.put("tsCode", value.getTsCode());
                    value.setFundInRecords(fundRecordMapper.findFundInRecord(object1));
                });
            }
        }
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 查询分页 on 2019/9/10 10:42
     *
     * @param pageNo pageNo @param pageSize pageSize @param jsonObject
     *               jsonObject @return @throws
     */
    private PageInfo<FundSuperviseAccept> findPage(int pageNo, int pageSize, JSONObject jsonObject) {
        PageHelper.startPage(pageNo, pageSize);
        List<FundSuperviseAccept> list = fundSuperviseAcceptMapper.findList(jsonObject);
        return new PageInfo<>(list);
    }

    /**
     * 缴款入账台账-分页 on 2019/9/11 16:56
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> paymentAccountEntryLedgerPage(int pn, int pageSize,
                                                       PaymentAccountEntryLedgerPageRequest request) {
        JSONObject jsonObject = new JSONObject();
        if (request.getCreatedAtStart() != null && !"".equals(request.getCreatedAtStart().trim())) {
            jsonObject.put("createdAtStart", DateUtils.dayMinTime(request.getCreatedAtStart()));
        }
        if (request.getCreatedAtEnd() != null && !"".equals(request.getCreatedAtEnd().trim())) {
            jsonObject.put("createdAtEnd", DateUtils.dayMaxTime(request.getCreatedAtEnd()));
        }
        if (request.getPayTimeStart() != null && !"".equals(request.getPayTimeStart().trim())) {
            jsonObject.put("payTimeStart", DateUtils.dayMinTime(request.getPayTimeStart()));
        }
        if (request.getPayTimeEnd() != null && !"".equals(request.getPayTimeEnd().trim())) {
            jsonObject.put("payTimeEnd", DateUtils.dayMaxTime(request.getPayTimeEnd()));
        }
        if (request.getPayCheckTimeStart() != null && !"".equals(request.getPayCheckTimeStart().trim())) {
            jsonObject.put("payCheckTimeStart", DateUtils.dayMinTime(request.getPayCheckTimeStart()));
        }
        if (request.getPayCheckTimeEnd() != null && !"".equals(request.getPayCheckTimeEnd().trim())) {
            jsonObject.put("payCheckTimeEnd", DateUtils.dayMaxTime(request.getPayCheckTimeEnd()));
        }
        if (request.getPayBank() != null && !"".equals(request.getPayBank().trim())) {
            jsonObject.put("payBank", request.getPayBank());
        }
        if (request.getType() != null) {
            jsonObject.put("type", request.getType().toString());
        }
        if (request.getPayCheck() != null) {
            jsonObject.put("payCheck", request.getPayCheck());
        }
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords().trim())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getUserName() != null && !"".equals(request.getUserName().trim())) {
            jsonObject.put("userName", request.getUserName());
        }
        if (request.getPayChecker() != null && !"".equals(request.getPayChecker().trim())) {
            jsonObject.put("payChecker", request.getPayChecker());
        }
        if (request.getBankCardNum() != null && !"".equals(request.getBankCardNum().trim())) {
            jsonObject.put("bankCardNum", request.getBankCardNum());
        }
        PageHelper.startPage(pn, pageSize);
        PageInfo<JSONObject> pageInfo = new PageInfo<>(fundRecordMapper.paymentAccountEntryLedgerPage(jsonObject));
        if (pageInfo.getList() != null && pageInfo.getList().size() > 0) {
            pageInfo.getList().forEach(value -> {
                value.put("fCode", value.get("fCode") != null ? value.get("fCode") : "");
                value.put("approvalFlow", value.get("approvalFlow") != null ? value.get("approvalFlow") : "");
                value.put("payCheck", value.get("payCheck") != null ? value.get("payCheck") : "");
                value.put("isReturn", value.get("isReturn") != null ? value.get("isReturn") : "");
                value.put("tsCode", value.get("tsCode") != null ? value.get("tsCode") : "");
                value.put("userId", value.get("userId") != null ? value.get("userId") : "");
                value.put("userName", value.get("userName") != null ? value.get("userName") : "");
                value.put("type", value.get("type") != null ? value.get("type") : "");
                value.put("amount", value.get("amount") != null ? value.get("amount") : "");
                value.put("payInMethod", value.get("payInMethod") != null ? value.get("payInMethod") : "");
                value.put("payer", value.get("payer") != null ? value.get("payer") : "");
                value.put("payFlag", value.get("payFlag") != null ? value.get("payFlag") : "");
                value.put("receiptCode", value.get("receiptCode") != null ? value.get("receiptCode") : "");
                value.put("payFlowCode", value.get("payFlowCode") != null ? value.get("payFlowCode") : "");
                value.put("createdAt", value.get("createdAt") != null ? value.get("createdAt") : "");
                value.put("payTime", value.get("payTime") != null ? value.get("payTime") : "");
                value.put("payBank", value.get("payBank") != null ? value.get("payBank") : "");
                value.put("payAccount", value.get("payAccount") != null ? value.get("payAccount") : "");
                value.put("payCheckerId", value.get("payCheckerId") != null ? value.get("payCheckerId") : "");
                value.put("payChecker", value.get("payChecker") != null ? value.get("payChecker") : "");
                value.put("payCheckTime", value.get("payCheckTime") != null ? value.get("payCheckTime") : "");
                value.put("netSignCode", value.get("netSignCode") != null ? value.get("netSignCode") : "");
                value.put("buyerName", value.get("buyerName") != null ? value.get("buyerName") : "");
                value.put("certificateNumber",
                        value.get("certificateNumber") != null ? value.get("certificateNumber") : "");
                value.put("ownershipNo", value.get("ownershipNo") != null ? value.get("ownershipNo") : "");
                value.put("sellerName", value.get("sellerName") != null ? value.get("sellerName") : "");
                value.put("remark", value.get("remark") != null ? value.get("remark") : "");
                value.put("flowInstanceId", value.get("flowInstanceId") != null ? value.get("flowInstanceId") : "");
                value.put("transferd", value.get("transferd") != null ? value.get("transferd") : "");
                value.put("hasTransfer", value.get("hasTransfer") != null ? value.get("hasTransfer") : "");
                value.put("payerId", value.get("payerId") != null ? value.get("payerId") : "");
                value.put("expenditureBank", value.get("expenditureBank") != null ? value.get("expenditureBank") : "");
                value.put("expenditureAccount",
                        value.get("expenditureAccount") != null ? value.get("expenditureAccount") : "");
                value.put("receiverAccount", value.get("receiverAccount") != null ? value.get("receiverAccount") : "");
                value.put("receiverBank", value.get("receiverBank") != null ? value.get("receiverBank") : "");
                value.put("acceptState", value.get("acceptState") != null ? value.get("acceptState") : "");
                value.put("refundState", value.get("refundState") != null ? value.get("refundState") : "");
            });
        }
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 划款出账台账-分页 on 2019/9/11 16:56
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> drawMoneyOutAccountLedgerPage(int pn, int pageSize,
                                                       DrawMoneyOutAccountLedgerPageRequest request) {
        JSONObject jsonObject = new JSONObject();
        if (request.getCreatedAtStart() != null && !"".equals(request.getCreatedAtStart().trim())) {
            jsonObject.put("createdAtStart", DateUtils.dayMinTime(request.getCreatedAtStart()));
        }
        if (request.getCreatedAtEnd() != null && !"".equals(request.getCreatedAtEnd().trim())) {
            jsonObject.put("createdAtEnd", DateUtils.dayMaxTime(request.getCreatedAtEnd()));
        }
        if (request.getTransferApplyTimeStart() != null && !"".equals(request.getTransferApplyTimeStart().trim())) {
            jsonObject.put("transferApplyTimeStart", DateUtils.dayMinTime(request.getTransferApplyTimeStart()));
        }
        if (request.getTransferApplyTimeEnd() != null && !"".equals(request.getTransferApplyTimeEnd().trim())) {
            jsonObject.put("transferApplyTimeEnd", DateUtils.dayMaxTime(request.getTransferApplyTimeEnd()));
        }
        if (request.getExpenditureTimeStart() != null && !"".equals(request.getExpenditureTimeStart().trim())) {
            jsonObject.put("expenditureTimeStart", DateUtils.dayMinTime(request.getExpenditureTimeStart()));
        }
        if (request.getExpenditureTimeEnd() != null && !"".equals(request.getExpenditureTimeEnd().trim())) {
            jsonObject.put("expenditureTimeEnd", DateUtils.dayMaxTime(request.getExpenditureTimeEnd()));
        }
        if (request.getExpenditureBank() != null && !"".equals(request.getExpenditureBank().trim())) {
            jsonObject.put("expenditureBank", request.getExpenditureBank());
        }
        if (request.getType() != null) {
            jsonObject.put("type", request.getType().toString());
        }
        if (request.getExpenditureCheck() != null) {
            jsonObject.put("expenditureCheck", request.getExpenditureCheck());
        }
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords().trim())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getUserName() != null && !"".equals(request.getUserName().trim())) {
            jsonObject.put("userName", request.getUserName());
        }
        if (request.getExpenditureChecker() != null && !"".equals(request.getExpenditureChecker().trim())) {
            jsonObject.put("expenditureChecker", request.getExpenditureChecker());
        }
        if (request.getBankCardNum() != null && !"".equals(request.getBankCardNum().trim())) {
            jsonObject.put("bankCardNum", request.getBankCardNum());
        }
        if (request.getIsRefund() != null && request.getIsRefund() > 0) {
            jsonObject.put("isRefund", request.getIsRefund());
        }
        PageHelper.startPage(pn, pageSize);
        PageInfo<JSONObject> info = new PageInfo<>(fundRecordMapper.drawMoneyOutAccountLedgerPage(jsonObject));
        if (info.getList().size() > 0) {
            for (JSONObject object : info.getList()) {
                object.put("fCode", object.get("fCode") != null ? object.get("fCode") : "");
                object.put("approvalFlow", object.get("approvalFlow") != null ? object.get("approvalFlow") : "");
                object.put("expenditureCheck",
                        object.get("expenditureCheck") != null ? object.get("expenditureCheck") : "");
                object.put("isRevoke", object.get("isRevoke") != null ? object.get("isRevoke") : "");
                object.put("tsCode", object.get("tsCode") != null ? object.get("tsCode") : "");
                object.put("userId", object.get("userId") != null ? object.get("userId") : "");
                object.put("userName", object.get("userName") != null ? object.get("userName") : "");
                object.put("dnCode", object.get("dnCode") != null ? object.get("dnCode") : "");
                object.put("type", object.get("type") != null ? object.get("type") : "");
                object.put("amount", object.get("amount") != null ? object.get("amount") : "");
                object.put("seller", object.get("seller") != null ? object.get("seller") : "");
                object.put("payBank", object.get("payBank") != null ? object.get("payBank") : "");
                object.put("payAccount", object.get("payAccount") != null ? object.get("payAccount") : "");
                object.put("expenditureBank",
                        object.get("expenditureBank") != null ? object.get("expenditureBank") : "");
                object.put("expenditureAccount",
                        object.get("expenditureAccount") != null ? object.get("expenditureAccount") : "");
                object.put("bankFlowCode", object.get("bankFlowCode") != null ? object.get("bankFlowCode") : "");
                object.put("payInMethod", object.get("payInMethod") != null ? object.get("payInMethod") : "");
                object.put("transferApplyTime",
                        object.get("transferApplyTime") != null ? object.get("transferApplyTime") : "");
                object.put("netSignCode", object.get("netSignCode") != null ? object.get("netSignCode") : "");
                object.put("buyerName", object.get("buyerName") != null ? object.get("buyerName") : "");
                object.put("certificateNumber",
                        object.get("certificateNumber") != null ? object.get("certificateNumber") : "");
                object.put("sellerName", object.get("sellerName") != null ? object.get("sellerName") : "");
                object.put("sellerCertificateNumber", object.get("sellerCertificateNumber") != null ? object.get("sellerCertificateNumber") : "");
                object.put("expenditureTime",
                        object.get("expenditureTime") != null ? object.get("expenditureTime") : "");
                object.put("remark", object.get("remark") != null ? object.get("remark") : "");
                object.put("flowInstanceId", object.get("flowInstanceId") != null ? object.get("flowInstanceId") : "");
                object.put("transferType", object.get("transferType") != null ? object.get("transferType") : "");
                object.put("bankName", object.get("bankName") != null ? object.get("bankName") : "");
                object.put("bankCardNum", object.get("bankCardNum") != null ? object.get("bankCardNum") : "");
                object.put("acceptState", object.get("acceptState") != null ? object.get("acceptState") : "");
                object.put("netSignCode", object.get("netSignCode") != null ? object.get("netSignCode") : "");
                object.put("expenditureChecker",
                        object.get("expenditureChecker") != null ? object.get("expenditureChecker") : "");
                object.put("expenditureCheckerId",
                        object.get("expenditureCheckerId") != null ? object.get("expenditureCheckerId") : "");
                object.put("seller", object.get("seller") != null ? object.get("seller") : "");
                object.put("refundState", object.get("refundState") != null ? object.get("refundState") : "");
                object.put("isReturn", object.get("isReturn") != null ? object.get("isReturn") : "");
                object.put("receiver", object.get("receiver") != null ? object.get("receiver") : "");
            }
        }
        return BaseResult.body(info, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 划款管理-选择需划付的资金 on 2019/9/18 14:59
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param tsCode   tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> needPayCapital(int pn, int pageSize, Long tsCode, Long dnCode, Long fundInCode) {
        JSONObject jsonObject = new JSONObject();
        if (tsCode != null && tsCode > 0) {
            jsonObject.put("tsCode", tsCode);
        }
        if (dnCode != null && dnCode > 0) {
            jsonObject.put("dnCode", dnCode);
        }
        if (fundInCode != null && fundInCode > 0) {
            jsonObject.put("fundInCode", fundInCode);
        }
        PageHelper.startPage(pn, pageSize);
        List<JSONObject> list = fundRecordMapper.needPayCapital(jsonObject);
        PageInfo<JSONObject> info = new PageInfo<>(list);
        if (info.getList() != null && info.getList().size() > 0) {
            info.getList().forEach(value -> {
                // 主键
                value.put("fCode", value.get("fCode") != null ? value.get("fCode") : "");
                // 流水号
                value.put("approvalFlow", value.get("approvalFlow") != null ? value.get("approvalFlow") : "");
                // 入账对账状态
                value.put("payCheck", value.get("payCheck") != null ? value.get("payCheck") : "");
                // 入账类型
                value.put("inType", value.get("inType") != null ? value.get("inType") : "");
                // 入账转账类型
                value.put("isAmount", value.get("isAmount") != null ? value.get("isAmount") : "");
                // 入账记账时间
                value.put("inCreatedAt", value.get("inCreatedAt") != null ? value.get("inCreatedAt") : "");
                // 入账时间
                value.put("payTime", value.get("payTime") != null ? value.get("payTime") : "");
                // 缴款人
                value.put("payer", value.get("payer") != null ? value.get("payer") : "");
                // 转入银行
                value.put("payBank", value.get("payBank") != null ? value.get("payBank") : "");
                // 转入账号
                value.put("payAccount", value.get("payAccount") != null ? value.get("payAccount") : "");
                // 入账备注
                value.put("inRemark", value.get("inRemark") != null ? value.get("inRemark") : "");
                // 已被划拨
                value.put("hasTransfer", value.get("hasTransfer") != null ? value.get("hasTransfer") : "");
            });
        }
        return BaseResult.ok(info);
    }

    /**
     * 退款管理-开具退款单 on 2019/9/18 14:59
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param tsCode   tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> openingRefundSlip(int pn, int pageSize, Long tsCode) {
        JSONObject jsonObject = new JSONObject();
        if (tsCode != null && tsCode > 0) {
            jsonObject.put("tsCode", tsCode);
        }
        PageHelper.startPage(pn, pageSize);
        return BaseResult.ok(new PageInfo<>(fundRecordMapper.openingRefundSlip(jsonObject)));
    }

    /**
     * 退款管理-开具退款单-业务信息 on 2019/9/18 14:59
     *
     * @param tsCode tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> businessInformation(Long tsCode) {
        JSONObject jsonObject = fundSuperviseAcceptMapper.businessInformation(tsCode);
        if (jsonObject == null) {
            return BaseResult.body(tsCode, ResultType.BUSINESS_ERROR).withMessage("该数据不存在");
        }
        // 案件编号
        jsonObject.put("tsCode", jsonObject.get("tsCode") != null ? jsonObject.get("tsCode") : "");
        // 买方姓名
        jsonObject.put("buyerName", jsonObject.get("buyerName") != null ? jsonObject.get("buyerName") : "");
        // 买方身份证
        jsonObject.put("buyerCertificateNumber",
                jsonObject.get("buyerCertificateNumber") != null ? jsonObject.get("buyerCertificateNumber") : "");
        // 卖方姓名
        jsonObject.put("sellerName", jsonObject.get("sellerName") != null ? jsonObject.get("sellerName") : "");
        // 卖方身份证
        jsonObject.put("sellerCertificateNumber",
                jsonObject.get("sellerCertificateNumber") != null ? jsonObject.get("sellerCertificateNumber") : "");
        // 经办人id
        jsonObject.put("userId", jsonObject.get("userId") != null ? jsonObject.get("userId") : "");
        // 经办人
        jsonObject.put("userName", jsonObject.get("userName") != null ? jsonObject.get("userName") : "");
        return BaseResult.ok(jsonObject);
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult cancelBusiness(BusinessCancelRequest request) {
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(request.getTsCode());
        if (fundSuperviseAccept.isTransferState()) {
            throw new BusinessError("已过户");
        }
        List<FundInRecord> fundInRecords = fundInRecordRepository.findByTsCode(request.getTsCode());
        for (FundInRecord f : fundInRecords) {
            if (!f.isPayCheck()) {
                throw new BusinessError("有未对账数据");
            }
        }
        List<TransferApply> transferApplies = transferApplyRepository.findByTsCode(request.getTsCode());
        for (TransferApply t : transferApplies) {
            if (t.getAuditState() == TransferApply.AuditStatus.PASSED) {
                throw new BusinessError("已经有有效的划款单");
            }
        }
        fundSuperviseAccept.setAcceptState(FundSuperviseAccept.AcceptState.CANCEL);
        fundSuperviseAccept.setCancelDate(new Date());
        return BaseResult.ok("Ok");
    }

    /**
     * 根据fcode查询fundin on 2019/9/26 20:21
     *
     * @param fCode fCode
     * @return BaseResult<?>
     */
    public BaseResult<?> getFundInByFCode(Long fCode) {
        if (fCode == null || fCode <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("fCode为空");
        }
        FundInRecord fundInRecord = fundInRecordRepository.findById(fCode).orElse(null);
        if (fundInRecord == null) {
            return BaseResult.body(fCode, ResultType.BUSINESS_ERROR).withMessage("该数据不存在");
        }
        return BaseResult.ok(fundInRecord);
    }

    public BaseResult<?> findFundInCancel() {
        try {
            String userId = UserUtils.getUser().getUserId();
            return BaseResult.ok(fundInRecordRepository.findByStateAndUserId(BaseFundRecord.State.CANCEL, userId));
        } catch (Exception e) {
            return BaseResult.ok(fundInRecordRepository.findByStateAndUserId(BaseFundRecord.State.CANCEL, "unknown"));
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> update(FundSuperviseAccept fundSuperviseAccept) {
        List<SignCredential> signCredentials = fundSuperviseAccept.getSignCredentials();
        fundSuperviseAccept = fundSuperviseAcceptRepository.save(fundSuperviseAccept);
        this.updateFiles(String.valueOf(fundSuperviseAccept.getTsCode()), signCredentials);
        return BaseResult.ok(fundSuperviseAcceptRepository.save(fundSuperviseAccept));
    }

    public boolean netSignExist(String netSignCode) {
        return fundSuperviseAcceptRepository.existsByNetSignCode(netSignCode);
    }

    public boolean fundInHasTransfer(CancelFundInRequest request) {
        List<TransferApply> transferApply = transferApplyRepository.findByFundInCode(request.getFCode());
        return transferApply.size() > 0;
    }

    public BaseResult checkBusiness(String netWorkSign) {
        if (fundSuperviseAcceptRepository.existsByNetSignCode(netWorkSign)) {
            List<FundSuperviseAccept> fundSuperviseAccepts = fundSuperviseAcceptRepository
                    .findByNetSignCode(netWorkSign);
            boolean doHas = false;
            // fixme: 所有入账全部对账且入账对应的所有出账全部对账才能受理新的案件
            List<FundInRecord> fundInRecords = fundInRecordRepository.findByNetSignCode(netWorkSign);
            List<FundOutRecord> fundOutRecords = fundOutRecordReporitory.findByNetSignCodeAndState(netWorkSign,
                    State.NORMAL);
            BigDecimal allIn = BigDecimal.ZERO;
            BigDecimal allOut = BigDecimal.ZERO;
            for (FundInRecord fi : fundInRecords) {
                allIn = allIn.add(fi.getAmount());
                if (!fi.isPayCheck()) {
                    return body("存在未对账的入账数据", ResultType.BUSINESS_ERROR);
                }
            }

            for (FundOutRecord fo : fundOutRecords) {
                allOut = allOut.add(fo.getAmount());
                if (!fo.isExpenditureCheck()) {
                    return body("存在未对账的出账数据", ResultType.BUSINESS_ERROR);
                }
            }
            if (!allIn.equals(allOut)) {
                return body("存在未划款的数据", ResultType.BUSINESS_ERROR);
            }

            for (FundSuperviseAccept fund : fundSuperviseAccepts) {
                if (fund.getAcceptState() == FundSuperviseAccept.AcceptState.HANDING
                        || fund.getAcceptState() == FundSuperviseAccept.AcceptState.FINISH) {
                    return body("案件已存在！", ResultType.BUSINESS_ERROR);
                }
            }
            return BaseResult.ok("可以受理");
        } else {
            return BaseResult.ok("可以受理");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> updateRefundFiels(RefundUploadFilesRequest refundUploadFilesRequest) {
        try {
            FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository
                    .findByTsCode(refundUploadFilesRequest.getTsCode());
            fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.WAIT_TRANSFER);
            signCredentialInfoService.deleteByBusiIdAndBusiCode(refundUploadFilesRequest.getSignCredentialList());
            signCredentialInfoService.save(refundUploadFilesRequest.getSignCredentialList(),
                    refundUploadFilesRequest.getBusiId());
            return BaseResult.ok(true);
        } catch (Exception ex) {
            return BaseResult.body(false, ResultType.BUSINESS_ERROR).withMessage(ex.getMessage());
        }
    }

    /**
     * 条件检查 on 2019/10/14 15:42
     *
     * @param fundSuperviseAccept fundSuperviseAccept
     * @return JSONObject
     */
    private JSONObject conditionInspect(FundSuperviseAccept fundSuperviseAccept) {
        JSONObject object = new JSONObject();
        // 是否存在贷款
        if (fundSuperviseAccept.isLoanExist()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("tsCode", fundSuperviseAccept.getTsCode());
            jsonObject.put("state", FundInRecord.State.NORMAL.toString());
            jsonObject.put("type", FundInRecord.Type.DOWNPAY.toString());
            List<FundInRecord> inRecord = fundRecordMapper.findFundInRecord(jsonObject);
            if (inRecord != null && inRecord.size() > 0) {
                // 入账是否为空
                if (fundInRecordRepository.findByTsCode(fundSuperviseAccept.getTsCode()) != null) {
                    JSONObject object1 = new JSONObject();
                    object1.put("tsCode", fundSuperviseAccept.getTsCode());
                    object1.put("state", FundInRecord.State.NORMAL.toString());
                    List<FundInRecord> fundInRecords = fundRecordMapper.findFundInRecord(object1);
                    BigDecimal amountSum = new BigDecimal(0);
                    for (FundInRecord record : fundInRecords) {
                        amountSum = amountSum.add(record.getAmount());
                    }
                    BigDecimal value = fundSuperviseAccept.getSuperviseAmount()
                            .subtract(fundSuperviseAccept.getLoanAmount());
                    if (amountSum.compareTo(value) == -1) {
                        // 小于
                        fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.DOWN_NOT_PAID_ALL);
                    } else if (amountSum.compareTo(value) == 0) {
                        // 等于
                        fundSuperviseAccept.setFundState(FundSuperviseAccept.FundState.LOAN_NOT_PAID);
                    } else if (amountSum.compareTo(value) == 1) {
                        // 大于
                        object.put("state", true);
                        object.put("message", "首付金额小于已入账金额，请检查");
                        return object;
                    }
                }
            }
        } else {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("tsCode", fundSuperviseAccept.getTsCode());
            jsonObject.put("state", FundInRecord.State.NORMAL.toString());
            jsonObject.put("type", FundInRecord.Type.LOAN.toString());
            List<FundInRecord> inRecord = fundRecordMapper.findFundInRecord(jsonObject);
            if (inRecord != null && inRecord.size() > 0) {
                object.put("state", true);
                object.put("message", "已有贷款入账数据,数据不可修改");
            }
        }
        object.put("state", false);
        return object;
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> setRefundStatePrinted(@NotBlank long tsCode) {
        if (fundSuperviseAcceptRepository.setRefundState(FundSuperviseAccept.RefundState.WAIT_UPLOAD, tsCode) > 0) {
            return BaseResult.ok("Ok");
        } else {
            throw new BusinessError("案件退回打印：出错");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean canCancelCase(BusinessCancelRequest request) {
        if (fundInRecordRepository.existsByTypeAndStateAndTsCode(BaseFundRecord.Type.LOAN, BaseFundRecord.State.NORMAL,
                request.getTsCode())) {
            return false;
        }
        if (fundInRecordRepository.existsByTypeAndStateAndTsCodeAndPayCheck(BaseFundRecord.Type.DOWNPAY,
                BaseFundRecord.State.NORMAL, request.getTsCode(), false)) {
            return false;
        }
        if (fundInRecordRepository.existsByTypeAndStateAndTsCodeAndPayCheck(BaseFundRecord.Type.FULLPAY,
                BaseFundRecord.State.NORMAL, request.getTsCode(), false)) {
            return false;
        }
        if (transferApplyRepository.existsByStateAndTsCode(TransferApply.State.NORMAL, request.getTsCode())) {
            return false;
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult printContract(PrintContractRequest request) throws Exception {
        BusinessProtocol businessProtocal = businessProtocolRepository.findByTsCode(request.getTsCode());
        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(request.getTsCode());
        if (fundSuperviseAccept == null) {
            throw new Exception("案件为空，交易编号为：" + request.getTsCode());
        }
        if (businessProtocal == null || businessProtocal.getContent() == null
                || businessProtocal.getContent().equals(businessProtocal.getNewContent())) {
            // 协议无变化或是新增的协议
            businessProtocal.setContent(businessProtocal.getNewContent());
            fundSuperviseAccept.setPrintTimes(fundSuperviseAccept.getPrintTimes() + 1);
            fundSuperviseAccept.setContractApproval(ContractApproval.PASS);
            businessProtocal.setPrinted(true);
        } else {
            // 协议有变化
            if (fundSuperviseAccept.getContractApproval() == ContractApproval.PASS) {
                // 通过
                businessProtocal.setContent(businessProtocal.getNewContent());
                fundSuperviseAccept.setPrintTimes(fundSuperviseAccept.getPrintTimes() + 1);
                fundSuperviseAccept.setContractApproval(ContractApproval.PASS);
                businessProtocal.setPrinted(true);
            } else {
                // 未通过
                return BaseResult.body("协议审核未通过", ResultType.BUSINESS_ERROR);
            }
        }
        businessProtocolRepository.save(businessProtocal);
        fundSuperviseAcceptRepository.save(fundSuperviseAccept);
        return BaseResult.ok("打印完成");
    }

    public BaseResult<?> turnBackFundIn(CancelFundInRequest request) {
        try {
            FundInRecord fi = fundInRecordRepository.findByFCode(request.getFCode()).get(0);
            fi.setReturn(true);
            fi.setCancelReson(request.getCancelReson());
            fi.setState(State.CANCEL);
            fundInRecordRepository.save(fi);
            return BaseResult.ok("退回完成！");
        } catch (NullPointerException nullEx) {
            return BaseResult.body("未找到相应的入账：" + request.getFCode(), ResultType.BUSINESS_ERROR);
        }
    }

    public boolean hasLoanIn(Long tsCode) {
        List<FundInRecord> fundInRecords = fundInRecordRepository.findByTsCodeAndType(tsCode,BaseFundRecord.Type.LOAN);
        return fundInRecords != null;
    }

    public boolean hasFundIn(long tsCode) {
        List<FundInRecord> fundInRecords = fundInRecordRepository.findByTsCodeAndType(tsCode,BaseFundRecord.Type.DOWNPAY);
        if(fundInRecords==null||fundInRecords.size()==0){
            fundInRecords = fundInRecordRepository.findByTsCodeAndType(tsCode,BaseFundRecord.Type.FULLPAY);
        }
        return fundInRecords != null;
    }

    public boolean doFundInCheck(long tsCode) {
        List<FundInRecord> fundInRecords = fundInRecordRepository.findByTsCode(tsCode);
        for (FundInRecord fi : fundInRecords) {
            if(fi.isPayCheck()){
                return false;
            }
        }
        return true;
    }
}
